﻿using MvCameraControl;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using VisionDesigner;
using PixelFormat = System.Drawing.Imaging.PixelFormat;

namespace VM.Common.Helper
{
    public class ImageTool
    {
        public static Bitmap BitmapImageToBitmap(BitmapImage bitmapImage)
        {
            // BitmapImage bitmapImage = new BitmapImage(new Uri("../Images/test.png", UriKind.Relative));

            using (MemoryStream outStream = new MemoryStream())
            {
                BitmapEncoder enc = new BmpBitmapEncoder();
                enc.Frames.Add(BitmapFrame.Create(bitmapImage));
                enc.Save(outStream);
                Bitmap bitmap = new Bitmap(outStream);

                return new Bitmap(bitmap);
            }
        }


        // ImageSource --> Bitmap
        public static System.Drawing.Bitmap ImageSourceToBitmap(ImageSource imageSource)
        {
            try
            {
                if (imageSource != null)
                {
                    BitmapSource m = (BitmapSource)imageSource;

                    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(m.PixelWidth, m.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb); // 坑点：选Format32bppRgb将不带透明度

                    System.Drawing.Imaging.BitmapData data = bmp.LockBits(
                        new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

                    m.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride);
                    bmp.UnlockBits(data);

                    return bmp;
                }
                else
                {
                    return new System.Drawing.Bitmap(1, 1);
                }
            }
            catch (Exception ex)
            {
                //  Log.Error("ImageSourceToBitmap 转换失败"  + ex.ToString());
                return new System.Drawing.Bitmap(1, 1);
            }

        }

        public static void ConvertMVDImage2Bitmap(CMvdImage cMvdImg, ref Bitmap cBitmapImg)
        {
            // 参数合法性判断
            if (null == cMvdImg)
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
            }

            // 判断像素格式
            if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 != cMvdImg.PixelFormat && MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 != cMvdImg.PixelFormat)
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
            }

            Int32 nImageWidth = Convert.ToInt32(cMvdImg.Width);
            Int32 nImageHeight = Convert.ToInt32(cMvdImg.Height);
            Int32 nChannelNum = 0;
            BitmapData bitmapData = null;
            byte[] bBitmapDataTemp = null;
            try
            {
                // 获取图像信息
                if (MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08 == cMvdImg.PixelFormat) // 灰度图
                {
                    cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format8bppIndexed);

                    // 灰度图需指定调色板
                    ColorPalette colorPalette = cBitmapImg.Palette;
                    for (int j = 0; j < 256; j++)
                    {
                        colorPalette.Entries[j] = System.Drawing.Color.FromArgb(j, j, j);
                    }
                    cBitmapImg.Palette = colorPalette;

                    bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
                                                                    , ImageLockMode.WriteOnly
                                                                    , PixelFormat.Format8bppIndexed);

                    // 灰度图不做深拷贝
                    bBitmapDataTemp = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
                    nChannelNum = 1;
                }
                else if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat) // 彩色图
                {
                    cBitmapImg = new Bitmap(nImageWidth, nImageHeight, PixelFormat.Format24bppRgb);
                    bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
                                                                , ImageLockMode.WriteOnly
                                                                , PixelFormat.Format24bppRgb);
                    // 彩色图做深拷贝
                    bBitmapDataTemp = new byte[cMvdImg.GetImageData().stDataChannel[0].arrDataBytes.Length];
                    Array.Copy(cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, bBitmapDataTemp, bBitmapDataTemp.Length);
                    nChannelNum = 3;
                }

                // bitmap彩色图按BGR存储，而MVDimg按RGB存储，改变存储顺序
                // 交换R和B
                if (MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3 == cMvdImg.PixelFormat)
                {
                    byte bTemp;
                    for (int i = 0; i < nImageWidth * nImageHeight; i++)
                    {
                        bTemp = bBitmapDataTemp[3 * i];
                        bBitmapDataTemp[3 * i] = bBitmapDataTemp[3 * i + 2];
                        bBitmapDataTemp[3 * i + 2] = bTemp;
                    }
                }

                // 考虑图像是否4字节对齐，bitmap要求4字节对齐，而mvdimage不要求对齐
                if (0 == nImageWidth % 4) // 4字节对齐时，直接拷贝
                {
                    Marshal.Copy(bBitmapDataTemp, 0, bitmapData.Scan0, nImageWidth * nImageHeight * nChannelNum);
                }
                else // 按步长逐行拷贝
                {
                    // 每行实际占用字节数
                    Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
                    // 每行首字节首地址
                    IntPtr bitmapDataRowPos = IntPtr.Zero;
                    for (int i = 0; i < nImageHeight; i++)
                    {
                        // 获取每行第一个像素值的首地址
                        bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
                        Marshal.Copy(bBitmapDataTemp, i * nImageWidth * nChannelNum, bitmapDataRowPos, nImageWidth * nChannelNum);
                    }
                }

                cBitmapImg.UnlockBits(bitmapData);
            }
            catch (MvdException ex)
            {
                if (null != cBitmapImg)
                {
                    cBitmapImg.UnlockBits(bitmapData);
                    cBitmapImg.Dispose();
                    cBitmapImg = null;
                }
                throw ex;
            }
            catch (System.Exception ex)
            {
                if (null != cBitmapImg)
                {
                    cBitmapImg.UnlockBits(bitmapData);
                    cBitmapImg.Dispose();
                    cBitmapImg = null;
                }
                throw ex;
            }
        }

        public static void ConvertBitmap2MVDImage(Bitmap cBitmapImg, CMvdImage cMvdImg)
        {
            // 参数合法性判断
            if (null == cBitmapImg || null == cMvdImg)
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
            }

            // 判断像素格式
            if (PixelFormat.Format8bppIndexed != cBitmapImg.PixelFormat && PixelFormat.Format24bppRgb != cBitmapImg.PixelFormat)
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
            }

            Int32 nImageWidth = cBitmapImg.Width;
            Int32 nImageHeight = cBitmapImg.Height;
            Int32 nChannelNum = 0;
            BitmapData bitmapData = null;

            try
            {
                // 获取图像信息
                if (PixelFormat.Format8bppIndexed == cBitmapImg.PixelFormat) // 灰度图
                {
                    bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
                                                                    , ImageLockMode.ReadOnly
                                                                    , PixelFormat.Format8bppIndexed);
                    cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                    nChannelNum = 1;
                }
                else if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat) // 彩色图
                {
                    bitmapData = cBitmapImg.LockBits(new Rectangle(0, 0, nImageWidth, nImageHeight)
                                                                , ImageLockMode.ReadOnly
                                                                , PixelFormat.Format24bppRgb);
                    cMvdImg.InitImage(Convert.ToUInt32(nImageWidth), Convert.ToUInt32(nImageHeight), MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3);
                    nChannelNum = 3;
                }

                // 考虑图像是否4字节对齐，bitmap要求4字节对齐，而mvdimage不要求对齐
                if (0 == nImageWidth % 4) // 4字节对齐时，直接拷贝
                {
                    Marshal.Copy(bitmapData.Scan0, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, 0, nImageWidth * nImageHeight * nChannelNum);
                }
                else // 按步长逐行拷贝
                {
                    // 每行实际占用字节数
                    Int32 nRowPixelByteNum = nImageWidth * nChannelNum + 4 - (nImageWidth * nChannelNum % 4);
                    // 每行首字节首地址
                    IntPtr bitmapDataRowPos = IntPtr.Zero;
                    for (int i = 0; i < nImageHeight; i++)
                    {
                        // 获取每行第一个像素值的首地址
                        bitmapDataRowPos = new IntPtr(bitmapData.Scan0.ToInt64() + nRowPixelByteNum * i);
                        Marshal.Copy(bitmapDataRowPos, cMvdImg.GetImageData().stDataChannel[0].arrDataBytes, i * nImageWidth * nChannelNum, nImageWidth * nChannelNum);
                    }
                }

                // bitmap彩色图按BGR存储，而MVDimg按RGB存储，改变存储顺序
                // 交换R和B
                if (PixelFormat.Format24bppRgb == cBitmapImg.PixelFormat)
                {
                    byte bTemp;
                    byte[] bMvdImgData = cMvdImg.GetImageData().stDataChannel[0].arrDataBytes;
                    for (int i = 0; i < nImageWidth * nImageHeight; i++)
                    {
                        bTemp = bMvdImgData[3 * i];
                        bMvdImgData[3 * i] = bMvdImgData[3 * i + 2];
                        bMvdImgData[3 * i + 2] = bTemp;
                    }
                }
            }
            finally
            {
                cBitmapImg.UnlockBits(bitmapData);
            }
        }

        public static void GetImvdImgFromCamerData(UInt32 nWidth, UInt32 nHeight, Byte[] byteGrapData, MvGvspPixelType enPixelType, ref CMvdImage? cMvdImage)
        {
            if (0 == nWidth || 0 == nHeight || null == byteGrapData)
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_PARAMETER_ILLEGAL);
            }
            if ((MvGvspPixelType.PixelType_Gvsp_Mono8 != enPixelType) && (MvGvspPixelType.PixelType_Gvsp_RGB8_Packed != enPixelType))
            {
                throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_SUPPORT);
            }
            if (null == cMvdImage)
            {
                cMvdImage = new CMvdImage();
            }
            MVD_IMAGE_DATA_INFO imagedate = new MVD_IMAGE_DATA_INFO();

            // 根据出图宽高初始化图像
            if (MvGvspPixelType.PixelType_Gvsp_Mono8 == enPixelType)
            {
                imagedate.stDataChannel[0].arrDataBytes = byteGrapData;
                imagedate.stDataChannel[0].nLen = nWidth * nHeight;
                imagedate.stDataChannel[0].nSize = nWidth * nHeight;
                imagedate.stDataChannel[0].nRowStep = nWidth;
                cMvdImage.InitImage(nWidth, nHeight, MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08, imagedate);
            }
            else if (MvGvspPixelType.PixelType_Gvsp_RGB8_Packed == enPixelType)
            {
                imagedate.stDataChannel[0].arrDataBytes = byteGrapData;
                imagedate.stDataChannel[0].nLen = nWidth * nHeight * 3;
                imagedate.stDataChannel[0].nSize = nWidth * nHeight * 3;
                imagedate.stDataChannel[0].nRowStep = nWidth * 3;
                cMvdImage.InitImage(nWidth, nHeight, MVD_PIXEL_FORMAT.MVD_PIXEL_RGB_RGB24_C3, imagedate);
            }
        }

    }
}
